package com.zookeeper.mine.study.utils;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;

import java.util.concurrent.CountDownLatch;

public class ZKCuratorUtils {

    private final static String connectString = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183";

    private final static Integer sessionTimeout = 1000;

    private final static Integer connectionTimeoutMs = 1000;

    private final static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {

        String parentPath = "/b";

        String childrenPath = parentPath + "/children";


        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);

        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(connectString,sessionTimeout,connectionTimeoutMs,retryPolicy);
        curatorFramework.start();

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        System.out.println(curatorFramework.checkExists().forPath(parentPath)!=null);
        System.out.println(curatorFramework.checkExists().forPath(parentPath)==null);
        if(curatorFramework.checkExists().forPath(parentPath) != null) {
            //curatorFramework.delete().forPath(childrenPath);
            //curatorFramework.delete().forPath(parentPath);
            System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaa");
            curatorFramework.delete().deletingChildrenIfNeeded().inBackground(new BackgroundCallback() {
                @Override
                public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                    System.out.println("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
                    countDownLatch.countDown();
                    System.out.println("curatorEvent==>"+curatorEvent.getPath()+"        "+curatorEvent.getType());
                }
            }).forPath(parentPath);
            countDownLatch.await();
        }
        System.out.println(curatorFramework.checkExists().forPath(parentPath)!=null);
        System.out.println(curatorFramework.checkExists().forPath(parentPath)==null);
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //PathChildrenCache用来监控一个ZNode的子节点. 当一个子节点增加， 更新，删除时
        PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework,parentPath,true);

        pathChildrenCache.start();

        PathChildrenCacheListener pathChildrenCacheListener = new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
                System.out.println("事件类型：" + pathChildrenCacheEvent.getType());
                if (null != pathChildrenCacheEvent.getData()) {
                    System.out.println("path==>" + pathChildrenCacheEvent.getData().getPath());
                    System.out.println("data==>" + new String(pathChildrenCacheEvent.getData().getData()));
                }
            }
        };

//        PathChildrenCacheListener pathChildrenCacheListener1 = (curatorFramework1,pathChildrenCacheEvent) -> {
//            System.out.println("事件类型：" + pathChildrenCacheEvent.getType());
//            if (null != pathChildrenCacheEvent.getData()) {
//                System.out.println("path==>" + pathChildrenCacheEvent.getData().getPath());
//                System.out.println("data==>" + new String(pathChildrenCacheEvent.getData().getData()));
//            }
//        };

        pathChildrenCache.getListenable().addListener(pathChildrenCacheListener);
//        pathChildrenCache.getListenable().addListener(pathChildrenCacheListener1);
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////


        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //NodeCache只是监听某一个特定的节点。
        final NodeCache nodeCache = new NodeCache(curatorFramework,parentPath);
        nodeCache.start();

//        NodeCacheListener nodeCacheListener = new NodeCacheListener() {
//            @Override
//            public void nodeChanged() throws Exception {
//
//                ChildData data = nodeCache.getCurrentData();
//
//                if (null != data) {
//                    System.out.println("节点数据：" + new String(nodeCache.getCurrentData().getData()));
//                } else {
//                    System.out.println("节点被删除!");
//                }
//            }
//        };

        NodeCacheListener nodeCacheListener1 = () -> {
            ChildData data = nodeCache.getCurrentData();
            if (null != data) {
                System.out.println("节点数据：" + new String(nodeCache.getCurrentData().getData()));
            } else {
                System.out.println("节点被删除!");
            }
        };

        //nodeCache.getListenable().addListener(nodeCacheListener);
        nodeCache.getListenable().addListener(nodeCacheListener1);
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        curatorFramework.checkExists().usingWatcher(new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("---------->"+watchedEvent.getType());
            }
        }).forPath(parentPath);

        //创建节点 设置值
        curatorFramework.createContainers(parentPath);
        curatorFramework.setData().forPath(parentPath,"aaa".getBytes());

        //读取 值
        byte [] data = curatorFramework.getData().forPath(parentPath);
        System.out.println("==>"+new String(data));

        //更新 设置 值
        curatorFramework.setData().forPath(parentPath,"abc".getBytes());
        data = curatorFramework.getData().forPath(parentPath);
        System.out.println("==>"+new String(data));

        //删除节点
        //curatorFramework.delete().forPath(parentPath);
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //创建节点 设置值
        curatorFramework.create().forPath(childrenPath,"children".getBytes());
        //读取 值
        data = curatorFramework.getData().forPath(childrenPath);
        System.out.println("==>"+new String(data));

        //更新 设置 值
        curatorFramework.setData().forPath(childrenPath,"abcchildren".getBytes());
        data = curatorFramework.getData().forPath(childrenPath);
        System.out.println("==>"+new String(data));

        //删除节点
        curatorFramework.delete().forPath(childrenPath);
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        curatorFramework.delete().forPath(parentPath);

        nodeCache.close();
        pathChildrenCache.close();
        curatorFramework.close();
    }

}
